/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.view.elements;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import org.jfonia.connect5.basics.MutableValueNode;
import org.jfonia.connect5.intervals.BasicDoubleInterval;
import org.jfonia.connect5.intervals.LinkedDoubleIntervalList;
import org.jfonia.constants.ViewConstants;

/**
 *
 * @author Rik Bauwens
 */
public class Caret
{
        private StaffPart parent;
        private LinkedDoubleIntervalList xNodes;
        private MutableValueNode<Double> height;
        private BasicDoubleInterval caretInterval;
        private int index;
        private Timer blinkTimer;
        private boolean set;
        private boolean visible;
    
        public Caret(StaffPart parent, LinkedDoubleIntervalList xNodes,
                     MutableValueNode<Double> height)
        {
                this.parent = parent;
                this.xNodes = xNodes;
                this.height = height;
                this.set = false;
                this.blinkTimer = new Timer(ViewConstants.CARET_BLINK_INTERVAL, new ActionListener()
                {
                        public void actionPerformed(ActionEvent e) {
                                visible = !visible;
                                repaint();
                        }
                });
                caretInterval = new BasicDoubleInterval();
                caretInterval.setDifference(2 * ViewConstants.CARET_SPACING +
                                                ViewConstants.CARET_THICKNESS);
                index = -1;
        }

        public void paint(Graphics2D g)
        {
                if(set && visible)
                {
                        g.setStroke(new BasicStroke((float) ViewConstants.CARET_THICKNESS));
                        g.drawLine((int) (caretInterval.getBegin()
                                         + ViewConstants.CARET_SPACING), 0,
                                   (int) (caretInterval.getBegin()
                                         + ViewConstants.CARET_SPACING), height.getValue().intValue());
                }
        }

        public void repaint()
        {
                parent.repaint();
        }

        public void set(double offset)
        {
                if(isSet())
                        remove();
                if(offset < xNodes.getEnd())
                {
                        //Check whether the xNodes list is empty
                        if(xNodes.size() > 0)
                        {
                                BasicDoubleInterval interval =
                                        (BasicDoubleInterval) xNodes.getIntervalFromValue(offset);
                                index = xNodes.indexOf(interval);

                                //Set the caret on the left of the symbol when the there has been clicked
                                //on that side of the symbol, set the caret to the right otherwise
                                if(interval.getEnd() - offset > offset - interval.getBegin())
                                        caretInterval.setBegin(interval.getBegin());
                                else
                                {
                                        caretInterval.setBegin(interval.getEnd() - caretInterval.getDifference());
                                        index++;
                                }
                        }
                }
                else
                {
                        //When there has been clicked on the right of the symbols,
                        //the absolute offset is greather than the width of the staffpart,
                        //set the caret after the last symbol
                        caretInterval.setBegin(xNodes.getEnd() - caretInterval.getDifference());
                        index = xNodes.size();
                }
                visible = true;
                blinkTimer.start();
                set = true;
        }

        public void next()
        {
                shift(1);
        }

        public void previous()
        {
                shift(-1);
        }

        public void shift(int posCount)
        {
                if(index + posCount >= 0 && index + posCount <= xNodes.size())
                {
                        if(posCount > 0)
                                caretInterval.setBegin((Double) xNodes.getIntervalFromIndex(index++ + posCount - 1).getEnd() - caretInterval.getDifference());
                        else if(posCount < 0)
                                caretInterval.setBegin((Double) xNodes.getIntervalFromIndex(index-- + posCount).getBegin());
                }
        }

/*
        public void set_deprecated(double offset)
        {
                if(isSet())
                        remove();
                int index = 0;
                if(offset <= xNodes.getEnd())
                {
                        //Check whether the xNodes list is empty
                        if(xNodes.size() > 0)
                        {
                                index = xNodes.indexOf(xNodes.getIntervalFromValue(offset));

                                //Set the caret on the left of the symbol when the there has been clicked
                                //on that side of the symbol, set the caret to the right otherwise
                                if((Double) xNodes.getIntervalFromIndex(index).getEnd() - offset
                                   < offset - (Double) xNodes.getIntervalFromIndex(index).getBegin())
                                    index ++;
                        }
                }
                else
                {
                        //When there has been clicked on the right of the symbols,
                        //the absolute offset is greather than the width of the staffpart,
                        //set the caret after the last symbol
                        index = xNodes.size();
                }
                if(caretInterval != null)
                        xNodes.remove(xNodes.indexOf(caretInterval));
                caretInterval = new BasicDoubleInterval();
                caretInterval.setDifference(2 * ViewConstants.CARET_SPACING +
                                                ViewConstants.CARET_THICKNESS);
                xNodes.insert(index, caretInterval);
                blinkTimer.start();
                set = true;
        }

        public void shift_deprecated(int posCount)
        {
                int index = xNodes.indexOf(caretInterval);
                if(caretInterval != null && index + posCount >= 0
                                         && index + posCount < xNodes.size())
                {
                        xNodes.remove(index);
                        xNodes.insert(index + posCount, caretInterval);
                }
        }

        public void remove_deprecated()
        {
                blinkTimer.stop();
                if(caretInterval != null && xNodes.indexOf(caretInterval) >= 0)
                {
                        xNodes.remove(xNodes.indexOf(caretInterval));
                        caretInterval = null;
                }
                set = false;
        }
 */

        public void remove()
        {
                visible = false;
                blinkTimer.stop();
                set = false;
        }

        public int getIndex()
        {
                return index;
        }

        public boolean isSet()
        {
                return set;
        }

        public boolean isValid()
        {
                return caretInterval.getBegin() >= 0;
        }
}
